package cn.hwm.proxy.rpcdemo;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * rpc服务端
 */
public class RpcFrameService {

    // 服务注册中心
    private static final ConcurrentHashMap<String, Class> serviceHolder = new ConcurrentHashMap<>();

    // 服务端执行器
    private static ExecutorService executorService = Executors.newFixedThreadPool(8);

    private int port;

    public RpcFrameService(int port) {
        this.port = port;
    }

    // 注册服务
    public void registerService(Class serviceInterface, Class impl) {
        serviceHolder.put(serviceInterface.getName(), impl);
    }

    private static class ServerTask implements Runnable {

        private Socket client;

        public ServerTask(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {

            try (ObjectOutputStream outputStream = new ObjectOutputStream(client.getOutputStream());
                 ObjectInputStream inputStream = new ObjectInputStream(client.getInputStream())) {

                String serviceName = inputStream.readUTF(); // 服务名
                String methodName = inputStream.readUTF(); // 方法名
                Class<?>[] parmTypes = (Class<?>[]) inputStream.readObject(); // 方法名的参数类型
                Object[] args = (Object[]) inputStream.readObject(); // 方法的参数

                Class serviceClass = serviceHolder.get(serviceName);
                Method method = serviceClass.getMethod(methodName, parmTypes);
                Object result = method.invoke(serviceClass.newInstance(), args);
                outputStream.writeObject(result);

            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    client.close();
                } catch (IOException e) {

                }
            }
        }
    }

    public void startService() throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        while (true){
            executorService.execute(new ServerTask(serverSocket.accept()));
        }
    }
}
